package com.songlanyun.modules.freighttemplate.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.math.BigDecimal;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songlanyun.common.drive.RootEntity;
import com.songlanyun.common.enums.OrderConstant;
import com.songlanyun.common.utils.SpringContextUtils;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.common.validator.group.AddGroup;
import com.songlanyun.common.validator.group.UpdateGroup;
import com.songlanyun.common.values.AddressInfo;
import com.songlanyun.modules.freighttemplate.service.FreightTemplateRuleService;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;

/**
 * 商家的物流模板表
 * 
 * @author lubo
 * @email sunlightcs@gmail.com
 * @date 2020-11-09 18:03:39
 */
@Data
@TableName("yxt_shop_freight_template")
public class FreightTemplate extends RootEntity<Integer,FreightTemplate> implements  Serializable {
	private static final long serialVersionUID = 1L;
	/**
	 * 
	 */
	@TableId
	@NotNull(message = "修改时必须指定Id", groups = {UpdateGroup.class})
	@Null(message = "新增时不能指定Id", groups = {AddGroup.class})
	private Integer id;
	/**
	 * 店铺id
	 */
	private Long shopId;
	/**
	 * 模板名称
	 */
	@NotBlank(message = "模板名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
	@Length(min = 1, max = 30, message = "模板名称长度在1-30个字", groups = {AddGroup.class, UpdateGroup.class})
	private String name;
	/**
	 * 是否免邮
	 */
	private Boolean freePost;
	/**
	 * 运费计算方式(0件，1重,2体积)
	 */
	private OrderConstant.FreightComputeMode freightComputeMode;
	/**
	 * 
	 */

	@TableField(fill = FieldFill.INSERT)
	private Date createTime;
	/**
	 *
	 */
	@TableField(fill = FieldFill.INSERT_UPDATE)
	private Date updateTime;

	/**
	 * 是否是默认模板
	 */
	private Boolean general;

	@Override
	public Integer getIdentity() {
		return getId();
	}

	@TableField(exist = false)
	private List<FreightTemplateRule> ruleList;

	/**
	 * 获得物流模板的所有规则
	 * @return
	 */
	public List<FreightTemplateRule> getRuleList()
	{
		FreightTemplateRuleService freightTemplateRuleService = (FreightTemplateRuleService) SpringContextUtils.getBean("freightTemplateRuleService");
		LambdaQueryWrapper<FreightTemplateRule> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(FreightTemplateRule::getFreightTemplateId, this.getId());
		ruleList = freightTemplateRuleService.list(queryWrapper);
		return ruleList;
	}


	/**
	 * 获得物流模板的默认
	 * @return
	 */
	@TableField(exist = false)
	private FreightTemplateRule defaultRule;
	public FreightTemplateRule getDefaultRule()
	{
		if(defaultRule==null) {
			Optional<FreightTemplateRule> optional = this.getRuleList().stream().filter(rule -> rule.getGeneral())
					.findFirst();
			if (optional == null || !optional.isPresent())
			{
				defaultRule = new FreightTemplateRule();
			}
			else {
				defaultRule =optional.get();
			}
		}
		return defaultRule;
	}

	/**
	 * 在当前模板的所有规则中找匹配的一条
	 * @param provinceCode
	 * @param cityCode
	 * @return
	 */
	private FreightTemplateRule findMatchRule(String provinceCode,String cityCode)
	{
		Optional<FreightTemplateRule> rule =  this.getRuleList().stream().filter(r->
				r.hasSet(provinceCode,cityCode)
		).findFirst();

		if(rule.isPresent()) return rule.get();
		return this.getDefaultRule();
	}


	/**
	 * 计算运算
	 * @param provinceCode
	 * @param cityCode
	 * @param totalNum
	 * @param totalWeight
	 * @param totalVolume
	 * @return
	 */
	public BigDecimal calculateFreight(String provinceCode,String cityCode, int totalNum, BigDecimal totalWeight, BigDecimal totalVolume)
	{
		if(this.getFreePost())  return BigDecimal.ZERO;
		FreightTemplateRule matchRule = this.findMatchRule(provinceCode,cityCode);

		BigDecimal startFreight = matchRule.getStartFreight();
		BigDecimal tempValue = BigDecimal.ZERO;
		switch (this.freightComputeMode)
		{
			case ITEM:
				int tempNum  = totalNum - matchRule.getStartStandards().intValue();
				tempValue = BigDecimal.valueOf(tempNum);
				break;
			case WEIGHT:
				tempValue  = MathUtils.subtract(totalWeight,matchRule.getStartStandards());
				break;
			case BULK:
				tempValue  = MathUtils.subtract(totalVolume,matchRule.getStartStandards());
				break;
		}

		if(tempValue.compareTo(BigDecimal.ZERO) <=0 || matchRule.getContinued().compareTo(BigDecimal.ZERO) <=0)
		{
			return startFreight;
		}
		else
		{
			BigDecimal round = new BigDecimal(Math.round(tempValue.doubleValue() / matchRule.getContinued().doubleValue()));
			BigDecimal continuedFreight = MathUtils.multiply(matchRule.getContinuedFreight(),round);
			return MathUtils.add(startFreight,continuedFreight);
		}
	}
}
